home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / ARCNET.ASM < prev    next >
Assembly Source File  |  1991-01-26  |  14KB  |  599 lines

  1. ;History:132,1
  2. ;Tue Feb 27 10:56:15 1990 send_pkt wasn't timing out properly.
  3. version    equ    0
  4.  
  5.     include    defs.asm
  6.  
  7. ;Ported from Philip Prindeville's arcnet driver for PCIP
  8. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  9.  
  10. ;  Copyright, 1988, 1989, Russell Nelson
  11.  
  12. ;   This program is free software; you can redistribute it and/or modify
  13. ;   it under the terms of the GNU General Public License as published by
  14. ;   the Free Software Foundation, version 1.
  15. ;
  16. ;   This program is distributed in the hope that it will be useful,
  17. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;   GNU General Public License for more details.
  20. ;
  21. ;   You should have received a copy of the GNU General Public License
  22. ;   along with this program; if not, write to the Free Software
  23. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25. code    segment    word public
  26.     assume    cs:code, ds:code
  27.  
  28.  
  29. ;Registers:
  30.  
  31. ;the following I/O addresses are mapped to the COM 9026
  32. IMASK        equ    0        ; writeable
  33. STATUS        equ    0        ; readable
  34. COMMAND        equ    1
  35. ;the following I/O addresses are mapped to the 8253 counter/timer
  36. CNTR0        equ    4
  37. CNTR1        equ    5
  38. CNTR2        equ    6
  39. MODE        equ    7
  40. ;reading the following I/O addresse performs a software reset.
  41. SW_RST        equ    8
  42.  
  43. ; time needed to do various things (in clock ticks)
  44. RST_IVAL    equ    4        ;reset
  45. SEND_IVAL    equ    4        ;send
  46.  
  47. ; ARP type for ARCnet
  48. ARP_ARC        equ    007h
  49.  
  50. ; broadcast address is nid 0
  51. ARC_BCAST    equ    0
  52.  
  53. ; packet sizes
  54. ARC_MTU        equ    253
  55. ARC_MnTU    equ    257
  56. ARC_XMTU    equ    508
  57. ;
  58. ;status/interrupt mask bit fields
  59. ;
  60. ST_TA        equ    001h        ; transmitter available
  61. ST_TMA        equ    002h        ; transmitted msg. ackd
  62. ST_RECON    equ    004h        ; system reconfigured
  63. ST_TEST        equ    008h        ; test flag
  64. ST_POR        equ    010h        ; power-on-reset
  65. ST_ETS1        equ    020h        ; unused
  66. ST_ETS2        equ    040h        ; unused
  67. ST_RI        equ    080h        ; receiver inhibited
  68.  
  69. ;
  70. ;in the command register, the following bits have these meanings:
  71. ;        0-2    command
  72. ;        3-4    page number (enable rvc/xmt)
  73. ;         7    rcv b'casts
  74.  
  75.  
  76. DSBL_XMT    equ    001h        ; disable transmitter
  77. DSBL_RCV    equ    002h        ; disable receiver
  78. ENBL_XMT    equ    003h        ; enable transmitter
  79. ENBL_RCV    equ    004h        ; enable receiver
  80. DFN_CONF    equ    005h        ; define configuration
  81. CLR_FLGS    equ    006h        ; clear flags
  82. LD_TST_FLG    equ    007h        ; load test flags
  83.  
  84. ; flags for clear flags operation
  85.  
  86. FL_POR        equ    008h        ; power-on-reset
  87. FL_RECON    equ    010h        ; system reconfigured
  88.  
  89. ; flags for load test flags operation
  90.  
  91. FL_TST        equ    008h        ; test flag (diagnostic)
  92.  
  93. ; byte deposited into first address of buffers when POR
  94. TSTWRD        equ    0321Q
  95.  
  96. ; handy macros for enable receiver/transmitter
  97.  
  98. BCAST        equ    080h        ; receiver only
  99. ;PAGE        equ(nn)    ((nn)<<3)
  100.  
  101. ; flags for define configuration
  102.  
  103. CONF_NORM    equ    000h        ; 1-253 byte packets
  104. CONF_XTND    equ    008h        ; 256-508 byte packets
  105.  
  106. ; macros to access buffers
  107. ;BUF    equ(page)    (((custom.c_basemem) + 512 * (page)))
  108.  
  109. ; ARCnet pseudo header -- note that syscode must occupy last byte...
  110.  
  111. arc_hdr    struc
  112. arc_sid        db    ?        ; source, valid on rcv
  113. arc_did        db    ?        ; destination, 0 = b'cast
  114. arc_cp        db    ?        ; continuation pointer. zero
  115.                     ; for extended packets
  116. arc_xcp        db    ?        ; extended cp, see above
  117. arc_syscode    db    ?        ; system code/pkt type
  118. arc_hdr    ends
  119.  
  120. ; designations for receiver/transmitter buffers.  sorry, no cleverness here
  121. RCVPAGE        equ    2
  122. XMTPAGE        equ    3
  123.  
  124. my_arcnet_id    db    0            ;my arcnet ID.
  125.  
  126.     public    int_no
  127. int_no        db    5,0,0,0        ; interrupt number.
  128. io_addr        dw    02e0h,0        ; I/O address for card (jumpers)
  129. mem_base    dw    0d800h,0
  130.  
  131.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  132. driver_class    db    8,0        ;ARCnet (from the packet spec)
  133. driver_type    db    1        ;Datapoint RIM (from the packet spec)
  134. driver_name    db    'ARCnet',0    ;name of the driver.
  135. driver_function    db    2
  136. parameter_list    label    byte
  137.     db    1    ;major rev of packet driver
  138.     db    9    ;minor rev of packet driver
  139.     db    14    ;length of parameter list
  140.     db    1    ;length of MAC-layer address
  141.     dw    507    ;MTU, including MAC headers
  142.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  143.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  144.     dw    0    ;(# of successive xmits) - 1
  145. int_num    dw    0    ;Interrupt # to hook for post-EOI
  146.             ;processing, 0 == none,
  147.  
  148.     public    rcv_modes
  149. rcv_modes    dw    4        ;number of receive modes in our table.
  150.         dw    0,0,0,rcv_mode_3
  151.  
  152.     include    movemem.asm
  153.  
  154.     public    as_send_pkt
  155. ; The Asynchronous Transmit Packet routine.
  156. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  157. ;   interrupts possibly enabled.
  158. ; Exit with nc if ok, or else cy if error, dh set to error number.
  159. ;   es:di and interrupt enable flag preserved on exit.
  160. as_send_pkt:
  161.     ret
  162.  
  163.     public    drop_pkt
  164. ; Drop a packet from the queue.
  165. ; Enter with es:di -> iocb.
  166. drop_pkt:
  167.     assume    ds:nothing
  168.     ret
  169.  
  170.     public    xmit
  171. ; Process a transmit interrupt with the least possible latency to achieve
  172. ;   back-to-back packet transmissions.
  173. ; May only use ax and dx.
  174. xmit:
  175.     assume    ds:nothing
  176.     ret
  177.  
  178.  
  179.     public    send_pkt
  180. send_pkt:
  181. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  182. ;  (only if the high-performance bit is set in driver_function)
  183. ;enter with ds:si -> packet, cx = packet length.
  184. ;exit with nc if ok, or else cy if error, dh set to error number.
  185.     assume    ds:nothing
  186.  
  187. ;Wait for transmitter ready.
  188.     loadport
  189.     setport    STATUS
  190.  
  191.     mov    ax,SEND_IVAL        ;only wait this long for it.
  192.     call    set_timeout        ;  otherwise we can't send.
  193. send_pkt_3:
  194.     in    al,dx            ;if not busy, exit.
  195.     and    al,ST_TA
  196.     jne    send_pkt_2
  197.     call    do_timeout        ;did we time out yet?
  198.     jne    send_pkt_3        ;no, not yet.
  199.  
  200.     setport    COMMAND            ;stop the transmit.
  201.     mov    al,DSBL_XMT
  202.     out    dx,al
  203.     mov    dh,CANT_SEND        ;timed out, can't send.
  204.     stc
  205.     ret
  206.  
  207. send_pkt_2:
  208. ;store the packet on the board.
  209.     mov    es,mem_base
  210.     mov    di,XMTPAGE * 512
  211.     movsw                ;move the SID and DID to the board.
  212.     sub    cx,2            ;leave them out of the count.
  213.  
  214.     cmp    cx,ARC_XMTU        ;is this one too big?
  215.     ja    send_pkt_toobig        ;yes, can't store it.
  216.     cmp    cx,ARC_MTU        ;is this one small enough
  217.     jbe    send_pkt_1        ;yes, just move it in.
  218.     cmp    cx,ARC_MnTU        ;is it *too* large AND *too* small?
  219.     jae    send_pkt_5        ;no.
  220.     mov    cx,ARC_MnTU        ;yes - use the larger size.
  221. send_pkt_5:
  222.     xor    al,al            ;use a zero cp to indicate xcp.
  223.     mov    ah,cl            ;store the length in xcp.
  224.     neg    ah
  225.     stosw
  226.     jmp    short send_pkt_4
  227. send_pkt_1:
  228.     mov    al,cl            ;store the length in cp.
  229.     neg    al
  230.     stosb
  231. send_pkt_4:
  232.     mov    ax,di            ;continue the put.
  233.     mov    al,cl            ;  advance the cp to its proper place.
  234.     neg    al
  235.     mov    di,ax
  236.     call    movemem
  237.  
  238. ;start the transmit.
  239.     mov    al,ENBL_XMT or (XMTPAGE shl 3)
  240.     loadport
  241.     setport    COMMAND
  242.     out    dx,al
  243.  
  244.     clc
  245.     ret
  246. send_pkt_toobig:
  247.     mov    dh,NO_SPACE
  248.     stc
  249.     ret
  250.  
  251.     public    get_address
  252. get_address:
  253. ;get the address of the interface.
  254. ;enter with es:di -> place to get the address, cx = size of address buffer.
  255. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  256.     assume    ds:code
  257.     cmp    cx,ARCADDR_LEN        ;make sure that we have enough room.
  258.     mov    dh,NO_SPACE
  259.     jb    get_address_2
  260.  
  261.     mov    al,my_arcnet_id        ;store our address.
  262.     stosb
  263.  
  264.     mov    cx,ARCADDR_LEN
  265.     clc
  266.     ret
  267. get_address_2:
  268.     stc
  269.     ret
  270.  
  271.  
  272. ;Set address on controller
  273.     public    set_address
  274. set_address:
  275.     assume    ds:nothing
  276. ;enter with ds:si -> address, CX = length of address.
  277. ;exit with nc if okay, or cy, dh=error if any errors.
  278.     mov    dh,CANT_SET
  279.     stc
  280.     ret
  281.  
  282.  
  283. rcv_mode_3:
  284. ;receive mode 3 is the only one we support, so we don't have to do anything.
  285.     ret
  286.  
  287.  
  288.     public    set_multicast_list
  289. set_multicast_list:
  290. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  291. ;return nc if we set all of them, or cy,dh=error if we didn't.
  292.     mov    dh,NO_MULTICAST
  293.     stc
  294.     ret
  295.  
  296.  
  297.     public    terminate
  298. terminate:
  299.     assume    ds:code
  300.     loadport
  301.     setport    IMASK
  302.     mov    al,0
  303.     out    dx,al
  304.  
  305.     setport COMMAND
  306.     mov    al,DSBL_RCV
  307.     out    dx,al
  308.     mov    al,DSBL_XMT
  309.     out    dx,al
  310.  
  311.     setport    STATUS            ;do we need to do this [rnn]?
  312.     in    al,dx
  313.  
  314.     ret
  315.  
  316.  
  317.     public    reset_interface
  318. reset_interface:
  319. ;reset the interface.
  320. ;we don't do anything.
  321.     ret
  322.  
  323.  
  324.     include    timeout.asm
  325.  
  326. ;called when we want to determine what to do with a received packet.
  327. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  328.     extrn    recv_find: near
  329.  
  330. ;called after we have copied the packet into the buffer.
  331. ;enter with ds:si ->the packet, cx = length of the packet.
  332.     extrn    recv_copy: near
  333.  
  334.     extrn    count_in_err: near
  335.     extrn    count_out_err: near
  336.  
  337.     public    recv
  338. recv:
  339. ;called from the recv isr.  All registers have been saved, and ds=cs.
  340. ;Upon exit, the interrupt will be acknowledged.
  341.     assume    ds:code
  342.  
  343. recv_1:
  344.     loadport            ;get the status to see if we got
  345.     setport    STATUS            ;  a false alarm.
  346.     in    al,dx
  347.     test    al,ST_RI
  348.     je    recv_2            ;yup, exit now.
  349.  
  350.     mov    es,mem_base
  351.     mov    bx,RCVPAGE * 512
  352.  
  353. ;decode data size.
  354.  
  355.     mov    cx,256            ;compute the actual length.
  356.     mov    al,es:[bx].arc_cp
  357.     or    al,al            ;is this a normal or continuation pkt?
  358.     jne    recv_3            ;go if normal.
  359.     mov    cx,512            ;extended packets have 512 max.
  360.     mov    al,es:[bx].arc_xcp
  361. recv_3:
  362.     xor    ah,ah
  363.     sub    cx,ax
  364.     add    cx,2            ;add in SID and DID.
  365.     mov    bl,al            ;use al as the low byte of the address.
  366.     mov    di,bx
  367.     mov    dl,driver_class
  368.     call    recv_find        ;look up our type.
  369.  
  370.     mov    ax,es            ;is this pointer null?
  371.     or    ax,di
  372.     je    recv_isr_9        ;yes - just free the frame.
  373.  
  374.     push    es            ;remember where the buffer pointer is.
  375.     push    di
  376.  
  377.     mov    ds,mem_base        ;copy the packet into their buffer.
  378.     assume    ds:nothing
  379.     mov    si,RCVPAGE * 512    ;  (don't worry about ds.
  380.     movsw                ;move SID and DID.
  381.     mov    ax,si
  382.     lodsb                ;get arc_cp.
  383.     or    al,al            ;extended?
  384.     jne    recv_5            ;no.
  385.     lodsb                ;yes - get arc_xcp.
  386. recv_5:
  387.     mov    si,ax            ;set the new pointer.
  388.     push    cx            ;move the data part of the packet.
  389.     sub    cx,2            ;don't move the two we've already
  390.     call    movemem            ;  moved.
  391.     pop    cx
  392.  
  393.     pop    si
  394.     pop    ds
  395.     assume    ds:nothing
  396.     call    recv_copy        ;tell them that we copied it.
  397.  
  398.     mov    ax,cs            ;restore our ds.
  399.     mov    ds,ax
  400.     assume    ds:code
  401.  
  402. recv_isr_9:
  403.  
  404.     loadport            ;enable reception again.
  405.     setport    COMMAND
  406.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST
  407.     out    dx,al
  408.  
  409.     jmp    recv_1
  410. recv_2:
  411.     ret
  412.  
  413.  
  414.     public    recv_exiting
  415. recv_exiting:
  416. ;called from the recv isr after interrupts have been acknowledged.
  417. ;Only ds and ax have been saved.
  418.     assume    ds:nothing
  419.     ret
  420.  
  421.  
  422. end_resident    label    byte
  423.  
  424.     public    usage_msg
  425. usage_msg    db    "usage: arcnet [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr> <mem_base>",CR,LF,'$'
  426.  
  427.     public    copyright_msg
  428. copyright_msg    db    "Packet driver for the DataPoint RIM (ARCnet), version ",'0'+majver,".",'0'+version,CR,LF
  429.         db    "Portions Copyright 1988 Philip Prindeville",CR,LF,'$'
  430.  
  431. no_arcnet_msg    db    "No ARCnet found at that address.",CR,LF,'$'
  432. failed_test_msg    db    "Failed self test.",CR,LF,'$'
  433.  
  434. int_no_name    db    "Interrupt number ",'$'
  435. io_addr_name    db    "I/O port ",'$'
  436. mem_base_name    db    "Memory address ",'$'
  437.  
  438.     extrn    set_recv_isr: near
  439.  
  440. ;enter with si -> argument string, di -> word to store.
  441. ;if there is no number, don't change the number.
  442.     extrn    get_number: near
  443.  
  444. ;enter with dx -> name of word, di -> dword to print.
  445.     extrn    print_number: near
  446.  
  447.     public    parse_args
  448. parse_args:
  449. ;exit with nc if all went well, cy otherwise.
  450.     mov    di,offset int_no
  451.     call    get_number
  452.     mov    di,offset io_addr
  453.     call    get_number
  454.     mov    di,offset mem_base
  455.     call    get_number
  456.     clc
  457.     ret
  458.  
  459.  
  460. no_arcnet_error:
  461.     mov    dx,offset no_arcnet_msg
  462.     mov    ah,9
  463.     int    21h
  464.     jmp    short error
  465. failed_test_error:
  466.     mov    dx,offset failed_test_msg
  467.     mov    ah,9
  468.     int    21h
  469. error:
  470.     stc
  471.     ret
  472.  
  473.  
  474.     public    etopen
  475. etopen:
  476. ;reset the board via the I/O reset port, then wait for it to become sane again.
  477.  
  478.     mov    ax,mem_base        ;test the memory first.
  479.     mov    cx,2048
  480.     call    memory_test
  481.     jne    no_arcnet_error
  482.  
  483.     mov    es,mem_base
  484.  
  485.     loadport
  486.     setport SW_RST
  487.     in    al,dx
  488.  
  489.     mov    ax,RST_IVAL
  490.     call    set_timeout
  491. etopen_1:
  492.     call    do_timeout
  493.     jne    etopen_1
  494.  
  495.     setport    STATUS
  496.     in    al,dx
  497.  
  498. ;since we've just reset:
  499. ;    reset the POR flag,
  500. ;    check the diagnostic byte in the buffer,
  501. ;    grab the node ID, and assign it to the host number.
  502.  
  503.     test    al,ST_POR
  504.     je    etopen_2
  505.  
  506.     setport    COMMAND
  507.     mov    al,CLR_FLGS or FL_POR or FL_RECON
  508.     out    dx,al
  509.  
  510.     mov    al,es:[0]
  511.     cmp    byte ptr es:[0],TSTWRD
  512.     je    etopen_3
  513.     jmp    failed_test_error    ;failed power on self-test.
  514. etopen_3:
  515.     mov    al,es:[1]
  516.     mov    my_arcnet_id,al
  517. etopen_2:
  518.  
  519. ;another simple diagnostic:
  520. ;    force test flag on in RIM,
  521. ;    check to see that it is set,
  522. ;    reset it.
  523.  
  524.     loadport
  525.     setport    COMMAND
  526.     mov    al,LD_TST_FLG or FL_TST
  527.     out    dx,al
  528.  
  529.     setport STATUS
  530.     in    al,dx
  531.  
  532.     test    al,FL_TST
  533.     jne    etopen_4
  534.     jmp    failed_test_error    ;failed forced self-test.
  535. etopen_4:
  536.     setport    COMMAND
  537.     mov    al,LD_TST_FLG
  538.     out    dx,al
  539.     setport STATUS
  540.     in    al,dx
  541.  
  542.     pushf
  543.     cli
  544.  
  545.     call    set_recv_isr
  546.  
  547. ;now we enable the board to interrupt
  548. ;us on packet received.  Not transmiter available
  549. ;(i.e. transmission complete).  We don't have
  550. ;any control over POR, since it is NMI...
  551. ;RECON seems useless.
  552.  
  553.     loadport
  554.     setport    IMASK
  555.     mov    al,ST_RI
  556.     out    dx,al
  557.  
  558.     ; we should allow extended packets
  559.     setport    COMMAND
  560.     mov    al,DFN_CONF or CONF_XTND
  561.     out    dx,al
  562.  
  563.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST;
  564.     out    dx,al
  565.  
  566.     popf
  567.  
  568.     mov    al, int_no        ; Get board's interrupt vector
  569.     add    al, 8
  570.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  571.     jb    set_int_num        ; No.
  572.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  573. set_int_num:
  574.     xor    ah, ah            ; Clear high byte
  575.     mov    int_num, ax        ; Set parameter_list int num.
  576.  
  577.     mov    dx,offset end_resident
  578.     clc
  579.     ret
  580.  
  581.     public    print_parameters
  582. print_parameters:
  583.     mov    di,offset int_no
  584.     mov    dx,offset int_no_name
  585.     call    print_number
  586.     mov    di,offset io_addr
  587.     mov    dx,offset io_addr_name
  588.     call    print_number
  589.     mov    di,offset mem_base
  590.     mov    dx,offset mem_base_name
  591.     call    print_number
  592.     ret
  593.  
  594.     include    memtest.asm
  595.  
  596. code    ends
  597.  
  598.     end
  599.